﻿#include "propertiesdlg.h"
#include "ui_propertiesdlg.h"
#include <QDebug>
#include <QMessageBox>
#include "drawobj.h"
#include "unitinfoeditor.h"
#include <QModelIndex>

PropertiesDlg::PropertiesDlg(GraphicsRectItem* i, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::PropertiesDlg),
    m_rectItem(i),
    m_tempUnit(i->getUnit())
{
    initUI();
    initPinsTable();
    initConstautsTable();
}

PropertiesDlg::~PropertiesDlg()
{
    delete ui;
}

void PropertiesDlg::initUI()
{
    ui->setupUi(this);
    ui->tabWidget->setTabText(0,"详细信息");
    ui->tabWidget->setTabText(1,"输入");
    ui->tabWidget->setTabText(2,"输出");
    ui->tabWidget->setTabText(3,"常量");
    setFixedSize(QSize(700, 600));

    m_pInputTable = ui->inputTable;
    m_pOutputTable = ui->outputTable;
    m_pConstautsTable = ui->constantsTable;
    m_unitInfoEditor = new UnitInfoEditor(ui->propertyTab);
    m_unitInfoEditor->setUnit(&m_tempUnit);
}

void PropertiesDlg::initPinsTable()
{
    setupTable();
    connectSignals();
    refreshTable();
}

void PropertiesDlg::initConstautsTable()
{
    m_pConstautsTable->setColumnCount(5);
    m_pConstautsTable->setHorizontalHeaderLabels({{"编号", "名称", "单位", "值", "描述"}});

    m_pConstautsTable->verticalHeader()->setVisible(false);
    m_pConstautsTable->setAlternatingRowColors(true);
    m_pConstautsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_pConstautsTable->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);

    connect(m_pConstautsTable, &QTableWidget::cellChanged, this, &PropertiesDlg::on_constantsHandleCellChange);
    connect(m_pConstautsTable, &QTableWidget::itemSelectionChanged, this, &PropertiesDlg::on_updateCurTableItem);
    connect(ui->constantsNewButton, &QPushButton::clicked, this, &PropertiesDlg::on_addConstaut);
    connect(ui->constantsDelButton, &QPushButton::clicked, this, &PropertiesDlg::on_delConstaut);
    refreshConstautsTable();
}

void PropertiesDlg::closeEvent(QCloseEvent *event)
{
    m_unitInfoEditor->onApplyClicked(); //关闭时同步数据

    if(m_rectItem->getUnit() == m_tempUnit)
    {
        event->accept();
        return;
    }

    QMessageBox::StandardButton ret;
    ret = QMessageBox::warning(this, tr("MDI"),
                 tr("data has been modified.\n"
                    "Do you want to save your changes?"),
                 QMessageBox::Save | QMessageBox::Discard
                 | QMessageBox::Cancel);
    if (ret == QMessageBox::Save)
        on_saveButtonClick();
    else if (ret == QMessageBox::Cancel)
        event->accept();
}

static void updateTempUnitPins(QTableWidgetItem* item, QList<Pin>& pins)
{
    Pin &pin = pins[item->row()];
    switch (item->column())
    {
       case 1: pin.name = item->text(); break;
       case 2: pin.unit = item->text(); break;
       case 3: pin.value = item->text(); break;
       case 4: pin.desc = item->text(); break;
    }
}

void PropertiesDlg::on_handleCellChange(int row, int column)
{
    QTableWidget* table = qobject_cast<QTableWidget*>(sender());
    if(!table || !m_rectItem || row < 0)
        return;

    QTableWidgetItem *item = table->item(row, column);
    if(table == m_pInputTable)
        updateTempUnitPins(item, m_tempUnit.inputPins);
    else
        updateTempUnitPins(item, m_tempUnit.outputPins);
}

void PropertiesDlg::on_addInputPin()
{
    QList<Pin>& inputPins = m_tempUnit.inputPins;
    QList<Pin>& outputPins = m_tempUnit.outputPins;
    Pin newPin = Pin();
    newPin.unitId = m_tempUnit.id;
    newPin.index = inputPins.size();
    newPin.isInputPin = true;
    newPin.dir = QString("left");

    inputPins.append(newPin);
    for(Pin& pin : outputPins)
        pin.index++;
    refreshTable();
}

void PropertiesDlg::on_delInputPin()
{
    if(!m_pCurTableItem || m_pCurTableItem->row() < 0 || m_pCurTableItem->row() >= m_pInputTable->rowCount())
        return;
    bool ok;
    int curPinIndex = m_pInputTable->item(m_pCurTableItem->row(), 0)->text().toInt(&ok);
    if(!ok)
        return;

    QList<Pin>& inputPins = m_tempUnit.inputPins;
    QList<Pin>& outputPins = m_tempUnit.outputPins;
    for(int i = 0; i< inputPins.size(); i++)
    {
        if(inputPins[i].index > curPinIndex)
        {
            inputPins[i].index--;
            continue;
        }

        if(inputPins[i].index == curPinIndex)
        {
            inputPins.removeAt(i);
            i--;
        }
    }
    for(Pin& pin : outputPins)
        pin.index--;
    refreshTable();
}

void PropertiesDlg::on_addOutputPin()
{
    QList<Pin>& inputPins = m_tempUnit.inputPins;
    QList<Pin>& outputPins = m_tempUnit.outputPins;
    Pin newPin = Pin();
    newPin.unitId = m_tempUnit.id;
    newPin.index = inputPins.size() + outputPins.size();
    newPin.isInputPin = false;
    newPin.dir = QString("left");

    outputPins.append(newPin);
    refreshTable();
}

void PropertiesDlg::on_delOutputPin()
{
    if(!m_pCurTableItem || m_pCurTableItem->row() < 0 || m_pCurTableItem->row() >= m_pOutputTable->rowCount())
        return;
    bool ok;
    int curPinIndex = m_pOutputTable->item(m_pCurTableItem->row(), 0)->text().toInt(&ok);
    if(!ok)
        return;

    //QList<Pin>& inputPins = m_tempUnit.inputPins;
    QList<Pin>& outputPins = m_tempUnit.outputPins;
    for(int i = 0; i< outputPins.size(); i++)
    {
        if(outputPins[i].index > curPinIndex)
        {
            outputPins[i].index--;
            continue;
        }

        if(outputPins[i].index == curPinIndex)
        {
            outputPins.removeAt(i);
            i--;
        }
    }
    refreshTable();
}

void PropertiesDlg::on_closeButtonClick()
{
    close();
}

void PropertiesDlg::on_saveButtonClick()
{
    m_unitInfoEditor->onApplyClicked();
    m_rectItem->setUnit(m_tempUnit);
    close();
}

void PropertiesDlg::on_updateButtonClick()
{
    m_rectItem->setUnit(m_tempUnit);
}

void PropertiesDlg::on_updateCurTableItem()
{
    QTableWidget* table = qobject_cast<QTableWidget*>(sender());
    if(!table || !m_rectItem)
        return;
    QList<QTableWidgetItem*> selectItems;
    if(table == m_pInputTable)
        selectItems = m_pInputTable->selectedItems();
    else if(table == m_pOutputTable)
        selectItems = m_pOutputTable->selectedItems();
    else if(table == m_pConstautsTable)
        selectItems = m_pConstautsTable->selectedItems();

    if(selectItems.isEmpty())
        m_pCurTableItem = nullptr;
    else
        m_pCurTableItem = selectItems[0];
}

void PropertiesDlg::on_constantsHandleCellChange(int row, int column)
{
    QTableWidgetItem *item = m_pConstautsTable->item(row, column);
    Unit::Constaut &constant = m_tempUnit.constants[item->row()];
    switch (item->column())
    {
       case 1: constant.name = item->text(); break;
       case 2: constant.unit = item->text(); break;
       case 3: constant.value = item->text(); break;
       case 4: constant.desc = item->text(); break;
    }
}

void PropertiesDlg::on_addConstaut()
{
    QList<Unit::Constaut>& constants = m_tempUnit.constants;
    Unit::Constaut newConstaut = Unit::Constaut();
    newConstaut.index = constants.size();
    constants.append(newConstaut);
    refreshConstautsTable();
}

void PropertiesDlg::on_delConstaut()
{
    if(!m_pCurTableItem || m_pCurTableItem->row() < 0 || m_pCurTableItem->row() >= m_pConstautsTable->rowCount())
        return;
    bool ok;
    int curPinIndex = m_pConstautsTable->item(m_pCurTableItem->row(), 0)->text().toInt(&ok);
    if(!ok)
        return;

    QList<Unit::Constaut>& constants = m_tempUnit.constants;
    for(int i = 0; i< constants.size(); i++)
    {
        if(constants[i].index > curPinIndex)
        {
            constants[i].index--;
            continue;
        }

        if(constants[i].index == curPinIndex)
        {
            constants.removeAt(i);
            i--;
        }
    }
    refreshConstautsTable();
}

void PropertiesDlg::setupTable()
{
    m_pInputTable->setColumnCount(6);
    m_pInputTable->setHorizontalHeaderLabels({{"编号", "名称", "单位", "值", "描述", "方向"}});

    m_pInputTable->verticalHeader()->setVisible(false);
    m_pInputTable->setAlternatingRowColors(true);
    m_pInputTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_pInputTable->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);

    m_pOutputTable->setColumnCount(6);
    m_pOutputTable->setHorizontalHeaderLabels({{"编号", "名称", "单位", "值", "描述", "方向"}});

    m_pOutputTable->verticalHeader()->setVisible(false);
    m_pOutputTable->setAlternatingRowColors(true);
    m_pOutputTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_pOutputTable->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
}

void PropertiesDlg::connectSignals()
{
    connect(m_pInputTable, &QTableWidget::cellChanged, this, &PropertiesDlg::on_handleCellChange);
    connect(m_pOutputTable, &QTableWidget::cellChanged, this, &PropertiesDlg::on_handleCellChange);
    connect(ui->inputNewButton, &QPushButton::clicked, this, &PropertiesDlg::on_addInputPin);
    connect(ui->inputDelButton, &QPushButton::clicked, this, &PropertiesDlg::on_delInputPin);
    connect(ui->outputNewButton, &QPushButton::clicked, this, &PropertiesDlg::on_addOutputPin);
    connect(ui->outputDelButton, &QPushButton::clicked, this, &PropertiesDlg::on_delOutputPin);
    connect(ui->cancleButton, &QPushButton::clicked, this, &PropertiesDlg::on_closeButtonClick);
    connect(ui->confirmButton, &QPushButton::clicked, this, &PropertiesDlg::on_saveButtonClick);
    connect(m_pInputTable, &QTableWidget::itemSelectionChanged, this, &PropertiesDlg::on_updateCurTableItem);
    connect(m_pOutputTable, &QTableWidget::itemSelectionChanged, this, &PropertiesDlg::on_updateCurTableItem);
//    if(m_unitInfoEditor)
//        connect(m_unitInfoEditor->applyButton, &QPushButton::clicked, this, &PropertiesDlg::on_updateButtonClick);
}

static void setRowData(QTableWidget* table, int row, const QStringList &data)
{
    for (int col = 0; col < data.size(); ++col)
    {
        QTableWidgetItem *item = new QTableWidgetItem(data[col]);
        if (col == 0)
            item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        else
            item->setFlags(item->flags() | Qt::ItemIsEditable);
        table->setItem(row, col, item);
    }
}

static void refreshTableFromPins(QTableWidget* table, QList<Pin>& pins)
{
    table->blockSignals(true);
    table->clearContents();
    table->setRowCount(pins.size());
    for (int i = 0; i < pins.size(); ++i)
    {
        const Pin &pin = pins[i];
        setRowData(table, i, {QString::number(pin.index), pin.name, pin.unit, pin.value, pin.desc});

        QComboBox *dirCombo = new QComboBox();
        dirCombo->addItems({"right", "down", "left", "up"});
        dirCombo->setCurrentText(pin.dir);
        table->setCellWidget(i, 5, dirCombo);
    }
    table->blockSignals(false);
}

static void refreshTableFromConstauts(QTableWidget* table, QList<Unit::Constaut>& constants)
{
    table->blockSignals(true);
    table->clearContents();
    table->setRowCount(constants.size());
    for (int i = 0; i < constants.size(); ++i)
    {
        const Unit::Constaut &constant = constants[i];
        setRowData(table, i, {QString::number(constant.index), constant.name, constant.unit, constant.value, constant.desc});
    }
    table->blockSignals(false);
}

static void setTableTextAlignment(QTableWidget* table)
{
    for(int row = 0; row < table->rowCount(); row++)
    {
        for(int col = 0; col < table->columnCount(); col++)
        {
            if(QTableWidgetItem* item = table->item(row, col))
                item->setTextAlignment(Qt::AlignCenter);
        }
    }
}

void PropertiesDlg::refreshTable()
{
    if (!m_rectItem)
        return;
    m_pCurTableItem = nullptr;
    refreshTableFromPins(m_pInputTable, m_tempUnit.inputPins);
    refreshTableFromPins(m_pOutputTable, m_tempUnit.outputPins);

    setTableTextAlignment(m_pInputTable);//居中显示
    setTableTextAlignment(m_pOutputTable);
}

void PropertiesDlg::refreshConstautsTable()
{
    if (!m_rectItem)
        return;
    m_pCurTableItem = nullptr;
    refreshTableFromConstauts(m_pConstautsTable, m_tempUnit.constants);
    setTableTextAlignment(m_pConstautsTable);
}


